package com.tangtang.core.basic;

import com.tangtang.core.hash.ConsistentHashUtil;

import java.util.Arrays;
import java.util.List;
import java.util.TreeMap;

/**
 * 一致性hash算法
 *
 * @param <S>
 * @author Administrator
 */
public class Shard<S> {
    private TreeMap<Integer, S> nodes; // 虚拟节点
    private List<S> shards; // 真实机器节点
    private final int NODE_NUM = 1000; // 每个机器节点关联的虚拟节点个数
    private Integer[] keys = null;

    /**
     * @param shards
     */
    public Shard(List<S> shards) {
        super();
        this.shards = shards;
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        // 初始化一致性hash环
        nodes = new TreeMap<Integer, S>();
        for (int i = 0; i != shards.size(); ++i) {
            // 每个真实机器节点都需要关联虚拟节点
            final S shardInfo = shards.get(i);

            for (int n = 0; n < NODE_NUM; n++) {
                // 一个真实机器节点关联NODE_NUM个虚拟节点
                nodes.put(ConsistentHashUtil.calculate("SHARD-" + i + "-NODE-" + n), shardInfo);
            }
        }
        keys = new Integer[nodes.keySet().size()];
        nodes.keySet().toArray(keys);
    }

    /**
     * @return
     */
    public List<S> getShard() {
        return shards;
    }

    public S getShard(String key) {
        if (key == null)
            return null;
        if (keys.length == 0)
            return null;

        int hashKey = ConsistentHashUtil.calculate(key);
        int index = Arrays.binarySearch(keys, hashKey);
        if (index < 0) {
            index = ~index;
            if (index == 0) {
                index = keys.length - 1;
            } else if (index >= keys.length) {
                index = 0;
            }
        }
        return nodes.get(keys[index]);
    }
}
